// Returns the current content document
function getContentDocument(browserID) {
    return getSelectedBrowser(browserID).contentDocument;
}

// Returns the current content window
function getContentWindow(browserID) {
    return getSelectedBrowser(browserID).contentWindow;
}

// Returns the document body element
function getDocumentBodyElement(contentDocument) {
    // If there is a body element
    if (contentDocument.body) {
        return contentDocument.body;
    } else {
        var bodyElementList = contentDocument.getElementsByTagName("body");

        // If there is a body element
        if (bodyElementList.length > 0) {
            return bodyElementList[0];
        }
    }

    return contentDocument.documentElement;
}

// Returns the document head element
function getDocumentHeadElement(contentDocument) {
    var headElementList = contentDocument.getElementsByTagName("head");

    // If there is a head element
    if (headElementList.length > 0) {
        return headElementList[0];
    }

    return contentDocument.documentElement;
}

// Gets all the documents from the current page
function getDocuments(contentWindow) {
    var documents = new Array();

    // If the frame is set
    if (contentWindow) {
        var frames = contentWindow.frames;
        var framesLength = frames.length;

        // If the frame document exists
        if (contentWindow.document) {
            documents.push(contentWindow.document);
        }

        // Loop through the frames
        for (var i = 0; i < framesLength; i++) {
            documents = documents.concat(getDocuments(frames[i]));
        }
    }

    return documents;
}

//get document from the current page with the frame ID
function getDocumentByFrameID(contentWindow, frameID)
{
    if(contentWindow) {
        var frames = contentWindow.frames;
        var framesLength = frames.length;
        
         // Loop through the frames
        for (var i = 0; i < framesLength; i++) {
            if(frames[i].id == frameID)
                return frames[i];
            else
                getDocumentByFrameID(frames[i], frameID);
        }
    }
    return null;    
}

//get document from the current page with the frame name
function getDocumentByFrameName(contentWindow, frameName)
{
    if(contentWindow) {
        var frames = contentWindow.frames;
        var framesLength = frames.length;
        
         // Loop through the frames
        for (var i = 0; i < framesLength; i++) {
            if(frames[i].name == frameName)
                return frames[i];
            else
                getDocumentByFrameName(frames[i], frameName);
        }
    }
    return null;    
}


// Get the ancestors of the element
function getElementAncestors(element) {
    var ancestors = getElementAncestorsInternal(element);

    // Reverse the list and remove the last element which is the original element
    ancestors.reverse();
    ancestors.pop();

    return ancestors;
}

// Recursively gets the ancestors of an element
function getElementAncestorsInternal(element) {
    var ancestors = new Array();

    // If the element is set
    if (element) {
        var parentElement = element.parentNode;

        // If the element has a tag name
        if (element.tagName) {
            ancestors.push(element);
        }

        // If there is a parent element
        if (parentElement) {
            ancestors = ancestors.concat(getElementAncestorsInternal(parentElement));
        }
    }

    return ancestors;
}

// Get the children of the element
function getElementChildren(element) {
    var children = new Array();

    // If the element is set
    if (element) {
        var child = null;
        var childNodes = element.childNodes;
        var childLength = childNodes.length;

        // Loop through the children
        for (var i = 0; i < childLength; i++) {
            child = childNodes[i];

            // If the child and tag name are set
            if (child && child.tagName) {
                children.push(child);
            }
        }
    }

    return children;
}

// Get the position of the element
function getElementPosition(element, xPosition) {
    var position = 0;

    // If the element is set
    if (element) {
        var elementOffsetParent = element.offsetParent;

        // If the element has an offset parent
        if (elementOffsetParent) {
            // While there is an offset parent
            while ((elementOffsetParent = element.offsetParent) != null) {
                // If getting the x position
                if (xPosition) {
                    position += element.offsetLeft;
                } else {
                    position += element.offsetTop;
                }

                element = elementOffsetParent;
            }
        } else {
            // If getting the x position
            if (xPosition) {
                position = element.offsetLeft;
            } else {
                position = element.offsetTop;
            }
        }
    }

    return position;
}

// Get the x position of the element
function getElementPositionX(element) {
    return getElementPosition(element, true);
}

// Get the y position of the element
function getElementPositionY(element) {
    return getElementPosition(element, false);
}

// Returns the text from an element
function getElementText(element) {
    var elementText = "";

    // If the element is set
    if (element) {
        var childNode = null;
        var childNodeList = element.childNodes;
        var childNodeLength = childNodeList.length;
        var childNodeType = null;

        // Loop through the child nodes
        for (var i = 0; i < childNodeLength; i++) {
            childNode = childNodeList[i];
            childNodeType = childNode.nodeType;

            // If the child node type is an element
            if (childNodeType == Node.ELEMENT_NODE) {
                elementText += getElementText(childNode);
            } else if (childNodeType == Node.TEXT_NODE) {
                elementText += childNode.nodeValue + " ";
            }
        }
    }

    return elementText;
}

// Returns the list of the images for the specified document
function getImagesForDocument(contentDocument, includeBackgroundImages, includeIcons) {
    var images = new Array();

    // If the content document is set
    if (contentDocument) {
        var backgroundImage = null;
        var computedStyle = null;
        var cssURI = CSSPrimitiveValue.CSS_URI;
        var documentURL = contentDocument.documentURI;
        var element = null;
        var image = null;
        var imageInterface = Components.interfaces.nsIDOMHTMLImageElement;
        var inputInterface = Components.interfaces.nsIDOMHTMLInputElement;
        var linkInterface = Components.interfaces.nsIDOMHTMLLinkElement;
        var treeWalker = contentDocument.createTreeWalker(contentDocument, NodeFilter.SHOW_ELEMENT, null, false);
        var url = Components.classes["@mozilla.org/network/standard-url;1"].createInstance(Components.interfaces.nsIURL);

        // While the tree walker has more nodes
        while ((element = treeWalker.nextNode()) != null) {
            // If this is an image element
            if (element instanceof imageInterface) {
                images.push(element);
            } else if (element instanceof inputInterface && element.src && element.type && element.type.toLowerCase() == "image") {
                image = new Image();
                url.spec = documentURL;
                image.src = url.resolve(element.src);

                // If this is not a chrome image
                if (image.src.indexOf("chrome://") != 0) {
                    images.push(image);
                }
            } else if (includeIcons && element instanceof linkInterface && element.href && element.href.indexOf("chrome://") != 0 && element.rel && element.rel.indexOf("icon") != -1) {
                image = new Image();
                url.spec = documentURL;
                image.src = url.resolve(element.href);

                images.push(image);
            } else if (includeBackgroundImages) {
                computedStyle = element.ownerDocument.defaultView.getComputedStyle(element, null);

                // If the computed style is set
                if (computedStyle) {
                    backgroundImage = computedStyle.getPropertyCSSValue("background-image");

                    // If this element has a background image and it is a URI
                    if (backgroundImage && backgroundImage.primitiveType == cssURI) {
                        image = new Image();
                        image.src = backgroundImage.getStringValue();

                        // If this is not a chrome image
                        if (image.src.indexOf("chrome://") != 0) {
                            images.push(image);
                        }
                    }
                }
            }
        }
    }

    return images;
}

// Returns the list of the objects for the specified document
function getObjectsForDocument(contentDocument) {
    var objects = new Array();

    // If the content document is set
    if (contentDocument) {
        var documentObjects = contentDocument.embeds;
        var documentObjectsLength = documentObjects.length;

        // Loop through the document objects
        for (var i = 0; i < documentObjectsLength; i++) {
            objects.push(documentObjects[i]);
        }
    }

    return objects;
}

// Returns the content document from a page load event
function getPageLoadEventContentDocument(event) {
    // Try to get the event targets
    try {
        var eventTarget = event.target;
        var originalTarget = event.originalTarget;

        // If the event targets are set and the original target is the document or the event target is the browser
        if (eventTarget && originalTarget && (originalTarget.nodeName == "#document")) {
            var contentDocument = eventTarget.contentDocument;

            // If the content document is not set and the original target default view parent is set
            if (!contentDocument && originalTarget.defaultView && originalTarget.defaultView.parent) {
                contentDocument = originalTarget.defaultView.parent.document;
            }

            // If the content document is set and has the same URI as the original target
            if (contentDocument && contentDocument.documentURI == originalTarget.documentURI) {
                return contentDocument;
            }
        }
    } catch(exception) {
        // Do nothing
    }

    return null;
}

// Returns the selected browser
function getSelectedBrowser(browserID) {
    //return window.top.getElementById(browserID);
    return document.getElementById(browserID);
    //return window.top.getBrowser().selectedBrowser;
}

// Returns the list of the scripts for the specified document
function getScriptsForDocument(contentDocument, includeInline) {
    var scripts = new Array();

    // If the content document is set
    if (contentDocument) {
        var documentScript = null;
        var documentScripts = contentDocument.getElementsByTagName("script");
        var documentScriptsLength = documentScripts.length;
        var documentURL = contentDocument.documentURI;

        // Loop through the document scripts
        for (var i = 0; i < documentScriptsLength; i++) {
            documentScript = documentScripts[i];

            // If including inline scripts or this is not inline
            if (includeInline || (documentScript.src && documentScript.src != documentURL)) {
                scripts.push(documentScript);
            }
        }
    }

    return scripts;
}

// Inserts the given child after the element
function insertAfter(child, after) {
    // If the child and after are set
    if (child && after) {
        var nextSibling = after.nextSibling;
        var parent = after.parentNode;

        // If the element has a next sibling
        if (nextSibling) {
            parent.insertBefore(child, nextSibling);
        } else {
            parent.appendChild(child);
        }
    }
}

// Inserts the given child as the first child of the element
function insertAsFirstChild(element, child) {
    // If the element and child are set
    if (element && child) {
        // If the element has child nodes
        if (element.hasChildNodes()) {
            element.insertBefore(child, element.firstChild);
        } else {
            element.appendChild(child);
        }
    }
}

// Returns true if the ancestor element is an ancestor of the element
function isAncestor(element, ancestorElement) {
    // If the element and ancestor element are set
    if (element && ancestorElement) {
        var parentElement = null;

        // Loop through the parent elements
        while ((parentElement = element.parentNode) != null) {
            // If the parent element is the ancestor element
            if (parentElement == ancestorElement) {
                return true;
            } else {
                element = parentElement;
            }
        }
    }

    return false;
}

// Returns true if the page has frames
function pageHasFrames(browserID) {
    // If the content document has a frame element
    if (getContentDocument(browserID).getElementsByTagName("frame").length > 0) {
        return true;
    }

    return false;
}

// Removes all child elements from an element
function removeAllChildElements(element) {
    // If the element is set
    if (element) {
        var childElements = element.childNodes;

        // Loop through the child elements
        for (var i = 0; i < childElements.length; i++) {
            element.removeChild(childElements[i]);
        }

        childElements = element.childNodes;

        // Loop through the child elements
        while (childElements.length > 0) {
            element.removeChild(childElements[0]);
        }
    }
}

// Removes all elements matching the XPath
function removeAllElementsByXPath(contentDocument, xPath) {
    var elementList = evaluateXPath(contentDocument, xPath);
    var elementsLength = elementList.length;

    // Loop through all the elements
    for (var i = 0; i < elementsLength; i++) {
        removeElement(elementList[i]);
    }

}

// Removes an element
function removeElement(element) {
    // If the element and it's parent node are set
    if (element && element.parentNode) {
        element.parentNode.removeChild(element);
    }
}